#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "debugcmd.h"

#define SOCKET_MSG_MAXLEN    256
#define SOCKET_FILE          "/tmp/socket_dcmd"
#define SOCKET_LISTEN_MAXNUM 5
#define DEBUGCMD_JSON_FILE   "/tmp/cmd.json"

int debugcmd_register(void);

int main()
{
	int ret = 0;
	int client_sockfd = 0;
	int server_sockfd = 0;
	char* retmsg = NULL;
	char mesg[SOCKET_MSG_MAXLEN];
	struct sockaddr_un client_addr;
	struct sockaddr_un server_addr;
	socklen_t len = sizeof(client_addr);
	ssize_t cnt = 0;

	ret = debugcmd_init();
	if (ret) {
		printf("err: debugcmd_init\n");
		return -1;
	}

	ret = debugcmd_register();
	if (ret) {
		printf("err: debugcmd_register\n");
		return -1;
	}

	ret = debugcmd_export(DEBUGCMD_JSON_FILE);
	if (ret) {
		printf("err: debugcmd_execute\n");
		return -1;
	}

	// ret = debugcmd_execute(char * str);

	/* delete the socket file */
	unlink(SOCKET_FILE);

	/* create a socket */
	server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (-1 == server_sockfd) {
		printf("err: socket\n");
		exit(1);
	}

	/* bind with the local file */
	server_addr.sun_family = AF_UNIX;
	strcpy(server_addr.sun_path, SOCKET_FILE);
	ret = bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if (-1 == ret) {
		printf("err: bind\n");
		exit(1);
	}

	/* listen */
	ret = listen(server_sockfd, SOCKET_LISTEN_MAXNUM);
	if (-1 == ret) {
		printf("err: listen\n");
		exit(1);
	}

	while (1) {
		/* waiting for client connection */
		client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_addr, &len);
		if (-1 == ret) {
			printf("err: accept\n");
			exit(1);
		}

		/* exchange data */
		memset(mesg, 0, sizeof(mesg));
		cnt = read(client_sockfd, &mesg, SOCKET_MSG_MAXLEN);
		if (0 >= cnt) {
			printf("err: read\n");
			exit(1);
		}

		/* show input string */
		// printf("input string is: \"%s\", cnt = %ld\r\n", mesg, cnt);

		/* try to execute */
		ret = debugcmd_execute(mesg);
		retmsg = ret ? "NG" : "OK";
		send(client_sockfd, retmsg, strlen(retmsg) + sizeof(char), 0);

		/* close the socket */
		ret = close(client_sockfd);
		if (-1 == ret) {
			printf("err: close\n");
			exit(1);
		}
	}

	return 0;
}

/*---------------------------------------------------------------------------------------------------------------------
 * 命令回调函数定义
 *-------------------------------------------------------------------------------------------------------------------*/

/**
 * @brief i2c 读函数
 * @retval 错误码
 */
int MAZ_CMD_i2c_read(void* cmd, char* param)
{
	uint32_t slave;
	uint32_t reg;

	sscanf(param, "0x%x 0x%x", &slave, &reg);

	printf("i2c read cmd is running\r\n");
	printf("slave = 0x%02x\r\n", slave);
	printf("reg   = 0x%02x\r\n", reg);

	return 0;
}

/**
 * @brief i2c 写函数
 * @retval 错误码
 */
int MAZ_CMD_i2c_write(void* cmd, char* param)
{
	uint32_t slave;
	uint32_t reg;
	uint32_t val;

	sscanf(param, "0x%x 0x%x 0x%x", &slave, &reg, &val);

	printf("i2c write cmd is running\r\n");
	printf("slave = 0x%02x\r\n", slave);
	printf("reg   = 0x%02x\r\n", reg);
	printf("val   = 0x%02x\r\n", val);

	return 0;
}

/**
 * @brief i2c dump函数
 * @retval 错误码
 */
int MAZ_CMD_i2c_dump(void* cmd, char* param)
{
	uint32_t slave;

	sscanf(param, "0x%x", &slave);

	printf("i2c dump cmd is running\r\n");
	printf("slave = 0x%02x\r\n", slave);

	return 0;
}

/**
 * @brief 系统推出函数
 * @retval 错误码
 */
int MAZ_CMD_exit(void* cmd, char* param)
{
	printf("exit.\r\n");
	system("stty icanon echo");
	exit(0);
	return 0;
}

/**
 * @brief 打印单个字符
 * @retval none
 */
void __io_putchar(char c)
{
	printf("%c", c);
	fflush(stdout);
}

/**
 * @brief 清屏函数
 * @retval 错误码
 */
int MAZ_CMD_clear(void* cmd, char* param)
{
	/* 基于 VT100 控制码实现清屏动作 */
	__io_putchar('\x1b');
	__io_putchar('[');
	__io_putchar('2');
	__io_putchar('J');
	__io_putchar('\x1b');
	__io_putchar('[');
	__io_putchar('H');
	return 0;
}

DEBUGCMD_MCMD i2c = { "i2c", "i2c bus debug command." };
DEBUGCMD_SCMD i2c_read = { " read", "i2c read <slave> <reg>.", MAZ_CMD_i2c_read };
DEBUGCMD_SCMD i2c_write = { "write ", "i2c wrtie <slave> <reg> <val>.", MAZ_CMD_i2c_write };
DEBUGCMD_SCMD i2c_dump = { "dump", "i2c dump <slave>.", MAZ_CMD_i2c_dump };
DEBUGCMD_MCMD sysexit = { "exit", "exit", MAZ_CMD_exit };
DEBUGCMD_MCMD clear = { "clear", "clear", MAZ_CMD_clear };

/**
 * @brief 注册命令函数
 * @retval 错误码
 */
int debugcmd_register(void)
{
	debugcmd_mcmd_register(&i2c);
	debugcmd_scmd_register(&i2c, &i2c_read);
	debugcmd_scmd_register(&i2c, &i2c_write);
	debugcmd_scmd_register(&i2c, &i2c_dump);
	debugcmd_mcmd_register(&sysexit);
	debugcmd_mcmd_register(&clear);
	return 0;
}
